home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrtools-1.10 / cdrecord / fifo.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-07  |  17.2 KB  |  785 lines

  1. /* @(#)fifo.c    1.22 00/05/07 Copyright 1989,1997 J. Schilling */
  2. #ifndef lint
  3. static    char sccsid[] =
  4.     "@(#)fifo.c    1.22 00/05/07 Copyright 1989,1997 J. Schilling";
  5. #endif
  6. /*
  7.  *    A "fifo" that uses shared memory between two processes
  8.  *
  9.  *    The actual code is a mixture of borrowed code from star's fifo.c
  10.  *    and a proposal from Finn Arne Gangstad <finnag@guardian.no>
  11.  *    who had the idea to use a ring buffer to handle average size chunks.
  12.  *
  13.  *    Copyright (c) 1989,1997 J. Schilling
  14.  */
  15. /*
  16.  * This program is free software; you can redistribute it and/or modify
  17.  * it under the terms of the GNU General Public License as published by
  18.  * the Free Software Foundation; either version 2, or (at your option)
  19.  * any later version.
  20.  *
  21.  * This program is distributed in the hope that it will be useful,
  22.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24.  * GNU General Public License for more details.
  25.  *
  26.  * You should have received a copy of the GNU General Public License
  27.  * along with this program; see the file COPYING.  If not, write to
  28.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  */
  30.  
  31. #define    DEBUG
  32. /*#define    XDEBUG*/
  33. #include <mconfig.h>
  34. #if    !defined(HAVE_SMMAP) && !defined(HAVE_USGSHM) && !defined(HAVE_DOSALLOCSHAREDMEM)
  35. #undef    FIFO            /* We cannot have a FIFO on this platform */
  36. #endif
  37. #ifdef    FIFO
  38. #if !defined(USE_MMAP) && !defined(USE_USGSHM)
  39. #define    USE_MMAP
  40. #endif
  41. #ifndef    HAVE_SMMAP
  42. #    undef    USE_MMAP
  43. #    define    USE_USGSHM    /* now SYSV shared memory is the default*/
  44. #endif
  45. #ifdef    USE_MMAP        /* Only want to have one implementation */
  46. #    undef    USE_USGSHM    /* mmap() is preferred            */
  47. #endif
  48.  
  49. #ifdef    HAVE_DOSALLOCSHAREDMEM    /* This is for OS/2 */
  50. #    undef    USE_MMAP
  51. #    undef    USE_USGSHM
  52. #    define    USE_OS2SHM
  53. #endif
  54.  
  55. #include <fctldefs.h>
  56. #include <sys/types.h>
  57. #if defined(HAVE_SMMAP) && defined(USE_MMAP)
  58. #include <sys/mman.h>
  59. #endif
  60. #include <stdio.h>
  61. #include <stdxlib.h>
  62. #include <unixstd.h>
  63. #include <waitdefs.h>
  64. #include <utypes.h>
  65. #include <standard.h>
  66. #include <errno.h>
  67. #include <signal.h>
  68. #include <libport.h>
  69. #include <schily.h>
  70.  
  71. #include "cdrecord.h"
  72.  
  73. #ifdef DEBUG
  74. #ifdef XDEBUG
  75. FILE    *ef;
  76. #define    USDEBUG1    if (debug) {if(s == owner_reader)fprintf(ef, "r");else fprintf(ef, "w");fflush(ef);}
  77. #define    USDEBUG2    if (debug) {if(s == owner_reader)fprintf(ef, "R");else fprintf(ef, "W");fflush(ef);}
  78. #else
  79. #define    USDEBUG1
  80. #define    USDEBUG2
  81. #endif
  82. #define    EDEBUG(a)    if (debug) error a
  83. #else
  84. #define    EDEBUG(a)
  85. #define    USDEBUG1
  86. #define    USDEBUG2
  87. #endif
  88.  
  89. #define palign(x, a)    (((char *)(x)) + ((a) - 1 - (((unsigned)((x)-1))%(a))))
  90.  
  91. typedef enum faio_owner {
  92.     owner_none,
  93.     owner_reader,
  94.     owner_writer,
  95.     owner_faio
  96. } fowner_t;
  97.  
  98. char    *onames[] = {
  99.     "none",
  100.     "reader",
  101.     "writer",
  102.     "faio"
  103. };
  104.  
  105. typedef struct faio {
  106.     int    len;
  107.     volatile fowner_t owner;
  108.     short    fd;
  109.     short    saved_errno;
  110.     char    *bufp;
  111. } faio_t;
  112.  
  113. struct faio_stats {
  114.     long    puts;
  115.     long    gets;
  116.     long    empty;
  117.     long    full;
  118.     long    done;
  119.     long    cont_low;
  120. } *sp;
  121.  
  122. #define    MIN_BUFFERS    3
  123.  
  124. #define    MSECS    1000
  125. #define    SECS    (1000*MSECS)
  126.  
  127. /*
  128.  * Note: WRITER_MAXWAIT & READER_MAXWAIT need to be greater than the SCSI
  129.  * timeout for commands that write to the media. This is currently 200s
  130.  * if we are in SAO mode.
  131.  */
  132. /* microsecond delay between each buffer-ready probe by writing process */
  133. #define    WRITER_DELAY    (20*MSECS)
  134. #define    WRITER_MAXWAIT    (240*SECS)    /* 240 seconds max wait for data */
  135.  
  136. /* microsecond delay between each buffer-ready probe by reading process */
  137. #define    READER_DELAY    (80*MSECS)
  138. #define    READER_MAXWAIT    (240*SECS)    /* 240 seconds max wait for reader */
  139.  
  140. LOCAL    char    *buf;
  141. LOCAL    char    *bufbase;
  142. LOCAL    char    *bufend;
  143. LOCAL    long    buflen;
  144.  
  145. extern    int    debug;
  146. extern    int    lverbose;
  147.  
  148. EXPORT    void    init_fifo    __PR((long));
  149. #ifdef    USE_MMAP
  150. LOCAL    char*    mkshare        __PR((int size));
  151. #endif
  152. #ifdef    USE_USGSHM
  153. LOCAL    char*    mkshm        __PR((int size));
  154. #endif
  155. #ifdef    USE_OS2SHM
  156. LOCAL    char*    mkos2shm    __PR((int size));
  157. #endif
  158.  
  159. EXPORT    BOOL    init_faio    __PR((int tracks, track_t *track, int));
  160. EXPORT    BOOL    await_faio    __PR((void));
  161. EXPORT    void    kill_faio    __PR((void));
  162. EXPORT    int    wait_faio    __PR((void));
  163. LOCAL    void    faio_reader    __PR((int tracks, track_t *track));
  164. LOCAL    void    faio_read_track    __PR((track_t *trackp));
  165. LOCAL    void    faio_wait_on_buffer __PR((faio_t *f, fowner_t s,
  166.                       unsigned long delay,
  167.                       unsigned long max_wait));
  168. LOCAL    int    faio_read_segment __PR((int fd, faio_t *f, int len));
  169. LOCAL    faio_t    *faio_ref    __PR((int n));
  170. EXPORT    int    faio_read_buf    __PR((int f, char *bp, int size));
  171. EXPORT    int    faio_get_buf    __PR((int f, char **bpp, int size));
  172. EXPORT    void    fifo_stats    __PR((void));
  173. EXPORT    int    fifo_percent    __PR((BOOL addone));
  174.  
  175.  
  176. EXPORT void
  177. init_fifo(fs)
  178.     long    fs;
  179. {
  180.     int    pagesize;
  181.  
  182.     if (fs == 0L)
  183.         return;
  184.  
  185. #ifdef    _SC_PAGESIZE
  186.     pagesize = sysconf(_SC_PAGESIZE);
  187. #else
  188.     pagesize = getpagesize();
  189. #endif
  190.     buflen = roundup(fs, pagesize) + pagesize;
  191.     EDEBUG(("fs: %ld buflen: %ld\n", fs, buflen));
  192.  
  193. #if    defined(USE_MMAP)
  194.     buf = mkshare(buflen);
  195. #endif
  196. #if    defined(USE_USGSHM)
  197.     buf = mkshm(buflen);
  198. #endif
  199. #if    defined(USE_OS2SHM)
  200.     buf = mkos2shm(buflen);
  201. #endif
  202.  
  203.     bufbase = buf;
  204.     bufend = buf + buflen;
  205.     EDEBUG(("buf: %X bufend: %X, buflen: %ld\n", buf, bufend, buflen));
  206.     buf = palign(buf, pagesize);
  207.     buflen -= buf - bufbase;
  208.     EDEBUG(("buf: %X bufend: %X, buflen: %ld (align %ld)\n", buf, bufend, buflen, buf - bufbase));
  209.  
  210.     /*
  211.      * Dirty the whole buffer. This can die with various signals if
  212.      * we're trying to lock too much memory
  213.      */
  214.     fillbytes(buf, buflen, '\0');
  215.  
  216. #ifdef    XDEBUG
  217.     if (debug)
  218.         ef = fopen("/tmp/ef", "w");
  219. #endif
  220. }
  221.  
  222. #ifdef    USE_MMAP
  223. LOCAL char *
  224. mkshare(size)
  225.     int    size;
  226. {
  227.     int    f;
  228.     char    *addr;
  229.  
  230. #ifdef    MAP_ANONYMOUS    /* HP/UX */
  231.     f = -1;
  232.     addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, f, 0);
  233. #else
  234.     if ((f = open("/dev/zero", O_RDWR)) < 0)
  235.         comerr("Cannot open '/dev/zero'.\n");
  236.     addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);
  237. #endif
  238.     if (addr == (char *)-1)
  239.         comerr("Cannot get mmap for %d Bytes on /dev/zero.\n", size);
  240.     close(f);
  241.  
  242.     if (debug) errmsgno(EX_BAD, "shared memory segment attached: %x\n", addr);
  243.  
  244.     return (addr);
  245. }
  246. #endif
  247.  
  248. #ifdef    USE_USGSHM
  249. #include <sys/ipc.h>
  250. #include <sys/shm.h>
  251. LOCAL char *
  252. mkshm(size)
  253.     int    size;
  254. {
  255.     int    id;
  256.     char    *addr;
  257.     /*
  258.      * Unfortunately, a declaration of shmat() is missing in old
  259.      * implementations such as AT&T SVr0 and SunOS.
  260.      * We cannot add this definition here because the return-type
  261.      * changed on newer systems.
  262.      *
  263.      * We will get a warning like this:
  264.      *
  265.      * warning: assignment of pointer from integer lacks a cast
  266.      * or
  267.      * warning: illegal combination of pointer and integer, op =
  268.      */
  269. /*    extern    char *shmat();*/
  270.  
  271.     if ((id = shmget(IPC_PRIVATE, size, IPC_CREAT|0600)) == -1)
  272.         comerr("shmget failed\n");
  273.  
  274.     if (debug) errmsgno(EX_BAD, "shared memory segment allocated: %d\n", id);
  275.  
  276.     if ((addr = shmat(id, (char *)0, 0600)) == (char *)-1)
  277.         comerr("shmat failed\n");
  278.  
  279.     if (debug) errmsgno(EX_BAD, "shared memory segment attached: %x\n", addr);
  280.  
  281.     if (shmctl(id, IPC_RMID, 0) < 0)
  282.         comerr("shmctl failed to detach shared memory segment\n");
  283.  
  284. #ifdef    SHM_LOCK
  285.     /*
  286.      * Although SHM_LOCK is standard, it seems that all versions of AIX
  287.      * ommit this definition.
  288.      */
  289.     if (shmctl(id, SHM_LOCK, 0) < 0)
  290.         comerr("shmctl failed to lock shared memory segment\n");
  291. #endif
  292.  
  293.     return (addr);
  294. }
  295. #endif
  296.  
  297. #ifdef    USE_OS2SHM
  298. LOCAL char *
  299. mkos2shm(size)
  300.     int    size;
  301. {
  302.     char    *addr;
  303.  
  304.     /*
  305.      * The OS/2 implementation of shm (using shm.dll) limits the size of one shared
  306.      * memory segment to 0x3fa000 (aprox. 4MBytes). Using OS/2 native API we have
  307.      * no such restriction so I decided to use it allowing fifos of arbitrary size.
  308.          */
  309.     if(DosAllocSharedMem(&addr,NULL,size,0X100L | 0x1L | 0x2L | 0x10L))
  310.         comerr("DosAllocSharedMem() failed\n");
  311.  
  312.     if (debug)
  313.         errmsgno(EX_BAD, "shared memory allocated at address: %x\n", addr);
  314.  
  315.     return (addr);
  316. }
  317. #endif
  318.  
  319. LOCAL    int    faio_buffers;
  320. LOCAL    int    faio_buf_size;
  321. LOCAL    int    buf_idx;
  322. LOCAL    pid_t    faio_pid;
  323. LOCAL    BOOL    faio_didwait;
  324.  
  325. /*#define    faio_ref(n)    (&((faio_t *)buf)[n])*/
  326.  
  327.  
  328. EXPORT BOOL
  329. init_faio(tracks, track, bufsize)
  330.     int    tracks;
  331.     track_t    *track;
  332.     int    bufsize;
  333. {
  334.     int    n;
  335.     faio_t    *f;
  336.     int    pagesize;
  337.     char    *base;
  338.  
  339.     if (buflen == 0L)
  340.         return (FALSE);
  341.  
  342. #ifdef    _SC_PAGESIZE
  343.     pagesize = sysconf(_SC_PAGESIZE);
  344. #else
  345.     pagesize = getpagesize();
  346. #endif
  347.  
  348.     faio_buf_size = bufsize;
  349.     f = (faio_t *)buf;
  350.  
  351.     /*
  352.      * Compute space for buffer headers.
  353.      * Round bufsize up to pagesize to make each FIFO segment
  354.      * properly page aligned.
  355.      */
  356.     bufsize = roundup(bufsize, pagesize);
  357.     faio_buffers = (buflen - sizeof(*sp)) / bufsize;
  358.     EDEBUG(("bufsize: %d buffers: %d hdrsize %d\n", bufsize, faio_buffers, faio_buffers * sizeof(struct faio)));
  359.  
  360.     /*
  361.      * Reduce buffer space by header space.
  362.      */
  363.     n = sizeof(*sp) + faio_buffers * sizeof(struct faio);
  364.     n = roundup(n, pagesize);
  365.     faio_buffers = (buflen-n) / bufsize;
  366.     EDEBUG(("bufsize: %d buffers: %d hdrsize %d\n", bufsize, faio_buffers, faio_buffers * sizeof(struct faio)));
  367.  
  368.     if (faio_buffers < MIN_BUFFERS) {
  369.         errmsgno(EX_BAD,
  370.             "write-buffer too small, minimum is %dk. Disabling.\n",
  371.                         MIN_BUFFERS*bufsize/1024);
  372.         return (FALSE);
  373.     }
  374.  
  375.     if (debug)
  376.         printf("Using %d buffers of %d bytes.\n", faio_buffers, faio_buf_size);
  377.  
  378.     f = (faio_t *)buf;
  379.     base = buf + roundup(sizeof(*sp) + faio_buffers * sizeof(struct faio),
  380.                 pagesize);
  381.  
  382.     for (n = 0; n < faio_buffers; n++, f++, base += bufsize) {
  383.         /* Give all the buffers to the reader process */
  384.         f->owner = owner_writer;
  385.         f->bufp = base;
  386.         f->fd = -1;
  387.     }
  388.     sp = (struct faio_stats *)f;    /* point past headers */
  389.     sp->gets = sp->puts = sp->done = 0L;
  390.  
  391.     faio_pid = fork();
  392.     if (faio_pid < 0)
  393.         comerr("fork(2) failed");
  394.  
  395.     if (faio_pid == 0) {
  396.         /* child process */
  397.         raisepri(1);        /* almost max priority */
  398.  
  399. #ifdef USE_OS2SHM
  400.         DosGetSharedMem(buf,3);    /* PAG_READ|PAG_WRITE */
  401. #endif
  402.         /* Ignoring SIGALRM cures the SCO usleep() bug */
  403. /*        signal(SIGALRM, SIG_IGN);*/
  404.         faio_reader(tracks, track);
  405.         /* NOTREACHED */
  406.     } else {
  407.         faio_didwait = FALSE;
  408.  
  409.         /* close all file-descriptors that only the child will use */
  410.         for (n = 1; n <= tracks; n++)
  411.             close(track[n].f);
  412.     }
  413.  
  414.     return (TRUE);
  415. }
  416.  
  417. EXPORT BOOL
  418. await_faio()
  419. {
  420.     int    n;
  421.     int    lastfd = -1;
  422.     faio_t    *f;
  423.  
  424.     /*
  425.      * Wait until the reader is active and has filled the buffer.
  426.      */
  427.     if (lverbose || debug) {
  428.         printf("Waiting for reader process to fill input buffer ... ");
  429.         flush();
  430.     }
  431.  
  432.     faio_wait_on_buffer(faio_ref(faio_buffers - 1), owner_reader,
  433.                 500*MSECS, 0);
  434.  
  435.     if (lverbose || debug)
  436.         printf("input buffer ready.\n");
  437.  
  438.     sp->empty = sp->full = 0L;    /* set correct stat state */
  439.     sp->cont_low = faio_buffers;    /* set cont to max value  */
  440.  
  441.     f = faio_ref(0);
  442.     for (n = 0; n < faio_buffers; n++, f++) {
  443.         if (f->fd != lastfd &&
  444.             f->fd == STDIN_FILENO && f->len == 0) {
  445.             errmsgno(EX_BAD, "Premature EOF on stdin.\n");
  446.             kill(faio_pid, SIGKILL);
  447.             return (FALSE);
  448.         }
  449.         lastfd = f->fd;
  450.     }
  451.     return (TRUE);
  452. }
  453.  
  454. EXPORT void
  455. kill_faio()
  456. {
  457.     if (faio_pid > 0)
  458.         kill(faio_pid, SIGKILL);
  459. }
  460.  
  461. EXPORT int
  462. wait_faio()
  463. {
  464.     if (faio_pid > 0 && !faio_didwait)
  465.         return (wait(0));
  466.     faio_didwait = TRUE;
  467.     return (0);
  468. }
  469.  
  470. LOCAL void
  471. faio_reader(tracks, track)
  472.     int    tracks;
  473.     track_t    *track;
  474. {
  475.     /* This function should not return, but _exit. */
  476.     int    trackno;
  477.  
  478.     if (debug)
  479.         printf("\nfaio_reader starting\n");
  480.  
  481.     for (trackno = 1; trackno <= tracks; trackno++) {
  482.         if (debug)
  483.             printf("\nfaio_reader reading track %d\n", trackno);
  484.         faio_read_track(&track[trackno]);
  485.     }
  486.     sp->done++;
  487.     if (debug)
  488.         printf("\nfaio_reader all tracks read, exiting\n");
  489.  
  490.     /* Prevent hang if buffer is larger than all the tracks combined */
  491.     if (sp->gets == 0)
  492.         faio_ref(faio_buffers - 1)->owner = owner_reader;
  493.  
  494. #ifdef    USE_OS2SHM
  495.     DosFreeMem(buf);
  496.     sleep(30000);    /* XXX If calling _exit() here the parent process seems to be blocked */
  497.             /* XXX This should be fixed soon */
  498. #endif
  499.     if (debug)
  500.         error("\nfaio_reader _exit(0)\n");
  501.     _exit(0);
  502. }
  503.  
  504. #ifndef    faio_ref
  505. LOCAL faio_t *
  506. faio_ref(n)
  507.     int    n;
  508. {
  509.     return (&((faio_t *)buf)[n]);
  510. }
  511. #endif
  512.  
  513.  
  514. LOCAL void
  515. faio_read_track(trackp)
  516.     track_t *trackp;
  517. {
  518.     int    fd = trackp->f;
  519.     int    bytespt = trackp->secsize * trackp->secspt;
  520.     int    l;
  521.     long    tracksize = trackp->tracksize;
  522.     long    bytes_read = 0L;
  523.     long    bytes_to_read;
  524.  
  525.     if (bytespt > faio_buf_size) {
  526.         comerrno(EX_BAD,
  527.         "faio_read_track fatal: secsize %d secspt %d, bytespt(%d) > %d !!\n",
  528.              trackp->secsize, trackp->secspt, bytespt,
  529.              faio_buf_size);
  530.     }
  531.  
  532.     do {
  533.         bytes_to_read = bytespt;
  534.         if (tracksize > 0) {
  535.             bytes_to_read = tracksize - bytes_read;
  536.             if (bytes_to_read > bytespt)
  537.                 bytes_to_read = bytespt;
  538.         }
  539.         l = faio_read_segment(fd, faio_ref(buf_idx), bytes_to_read);
  540.         if (++buf_idx >= faio_buffers)
  541.             buf_idx = 0;
  542.         if (l <= 0)
  543.             break;
  544.         bytes_read += l;
  545.     } while (tracksize < 0 || bytes_read < tracksize);
  546.  
  547.     close(fd);    /* Don't keep files open longer than neccesary */
  548. }
  549.  
  550. LOCAL void
  551. faio_wait_on_buffer(f, s, delay, max_wait)
  552.     faio_t    *f;
  553.     fowner_t s;
  554.     unsigned long delay;
  555.     unsigned long max_wait;
  556. {
  557.     unsigned long max_loops;
  558.  
  559.     if (f->owner == s)
  560.         return;        /* return immediately if the buffer is ours */
  561.  
  562.     if (s == owner_reader)
  563.         sp->empty++;
  564.     else
  565.         sp->full++;
  566.  
  567.     max_loops = max_wait / delay + 1;
  568.  
  569.     while (max_wait == 0 || max_loops--) {
  570.         USDEBUG1;
  571.         usleep(delay);
  572.         USDEBUG2;
  573.  
  574.         if (f->owner == s)
  575.             return;
  576.     }
  577.     if (debug) {
  578.         errmsgno(EX_BAD,
  579.         "%lu microseconds passed waiting for %d current: %d idx: %d\n",
  580.         max_wait, s, f->owner, (f - faio_ref(0))/sizeof(*f));
  581.     }
  582.     comerrno(EX_BAD, "faio_wait_on_buffer for %s timed out.\n",
  583.     (s > owner_faio || s < owner_none) ? "bad_owner" : onames[s]);
  584. }
  585.  
  586. LOCAL int
  587. faio_read_segment(fd, f, len)
  588.     int    fd;
  589.     faio_t    *f;
  590.     int    len;
  591. {
  592.     int l;
  593.  
  594.     faio_wait_on_buffer(f, owner_writer, WRITER_DELAY, WRITER_MAXWAIT);
  595.  
  596.     f->fd = fd;
  597.     l = read_buf(fd, f->bufp, len);
  598.     f->len = l;
  599.     f->saved_errno = errno;
  600.     f->owner = owner_reader;
  601.  
  602.     sp->puts++;
  603.  
  604.     return l;
  605. }
  606.  
  607. EXPORT int
  608. faio_read_buf(fd, bp, size)
  609.     int fd;
  610.     char *bp;
  611.     int size;
  612. {
  613.     char *bufp;
  614.  
  615.     int len = faio_get_buf(fd, &bufp, size);
  616.     if (len > 0) {
  617.         movebytes(bufp, bp, len);
  618.     }
  619.     return len;
  620. }
  621.  
  622. EXPORT int
  623. faio_get_buf(fd, bpp, size)
  624.     int fd;
  625.     char **bpp;
  626.     int size;
  627. {
  628.     faio_t    *f;
  629.     int    len;
  630.  
  631. again:
  632.     f = faio_ref(buf_idx);
  633.     if (f->owner == owner_faio) {
  634.         f->owner = owner_writer;
  635.         if (++buf_idx >= faio_buffers)
  636.             buf_idx = 0;
  637.         f = faio_ref(buf_idx);
  638.     }
  639.  
  640.     if ((sp->puts - sp->gets) < sp->cont_low && sp->done == 0) {
  641.         EDEBUG(("gets: %d puts: %d cont: %d low: %d\n", sp->gets, sp->puts, sp->puts - sp->gets, sp->cont_low));
  642.         sp->cont_low = sp->puts - sp->gets;
  643.     }
  644.     faio_wait_on_buffer(f, owner_reader, READER_DELAY, READER_MAXWAIT);
  645.     len = f->len;
  646.     
  647.     if (f->fd != fd) {
  648.         if (f->len == 0) {
  649.             /*
  650.              * If the tracksize for this track was known, and
  651.              * the tracksize is 0 mod bytespt, this happens.
  652.              */
  653.             goto again;
  654.         }
  655.         comerrno(EX_BAD,
  656.         "faio_get_buf fatal: fd=%d, f->fd=%d, f->len=%d f->errno=%d\n",
  657.         fd, f->fd, f->len, f->saved_errno);
  658.     }
  659.     if (size < len) {
  660.         comerrno(EX_BAD,
  661.         "unexpected short read-attempt in faio_get_buf. size = %d, len = %d\n",
  662.         size, len);
  663.     }
  664.  
  665.     if (len < 0)
  666.         errno = f->saved_errno;
  667.  
  668.     sp->gets++;
  669.  
  670.     *bpp = f->bufp;
  671.     f->owner = owner_faio;
  672.     return len;
  673. }
  674.  
  675. EXPORT void
  676. fifo_stats()
  677. {
  678.     if (sp == NULL)    /* We might not use a FIFO */
  679.         return;
  680.  
  681.     errmsgno(EX_BAD, "fifo had %ld puts and %ld gets.\n",
  682.         sp->puts, sp->gets);
  683.     errmsgno(EX_BAD, "fifo was %ld times empty and %ld times full, min fill was %ld%%.\n",
  684.         sp->empty, sp->full, (100L*sp->cont_low)/faio_buffers);
  685. }
  686.  
  687. EXPORT int
  688. fifo_percent(addone)
  689.     BOOL    addone;
  690. {
  691.     int    percent;
  692.  
  693.     if (buflen == 0L)
  694.         return (-1);
  695.     if (sp->done)
  696.         return (100);
  697.     percent = (100*(sp->puts + 1 - sp->gets)/faio_buffers);
  698.     if (percent > 100)
  699.         return (100);
  700.     return (percent);
  701. }
  702. #else    /* FIFO */
  703.  
  704. #include <standard.h>
  705. #include <sys/types.h>
  706. #include <utypes.h>
  707.  
  708. #include "cdrecord.h"
  709.  
  710. EXPORT    void    init_fifo    __PR((long));
  711. EXPORT    BOOL    init_faio    __PR((int tracks, track_t *track, int));
  712. EXPORT    BOOL    await_faio    __PR((void));
  713. EXPORT    void    kill_faio    __PR((void));
  714. EXPORT    int    wait_faio    __PR((void));
  715. EXPORT    int    faio_read_buf    __PR((int f, char *bp, int size));
  716. EXPORT    int    faio_get_buf    __PR((int f, char **bpp, int size));
  717. EXPORT    void    fifo_stats    __PR((void));
  718. EXPORT    int    fifo_percent    __PR((BOOL addone));
  719.  
  720.  
  721. EXPORT void
  722. init_fifo(fs)
  723.     long    fs;
  724. {
  725.     errmsgno(EX_BAD, "Fifo not supported.\n");
  726. }
  727.  
  728. EXPORT BOOL
  729. init_faio(tracks, track, bufsize)
  730.     int    tracks;
  731.     track_t    *track;
  732.     int    bufsize;
  733. {
  734.     return (FALSE);
  735. }
  736.  
  737. EXPORT BOOL
  738. await_faio()
  739. {
  740.     return (TRUE);
  741. }
  742.  
  743. EXPORT void
  744. kill_faio()
  745. {
  746. }
  747.  
  748. EXPORT int
  749. wait_faio()
  750. {
  751.     return (0);
  752. }
  753.  
  754. EXPORT int
  755. faio_read_buf(fd, bp, size)
  756.     int fd;
  757.     char *bp;
  758.     int size;
  759. {
  760.     return (0);
  761. }
  762.  
  763. EXPORT int
  764. faio_get_buf(fd, bpp, size)
  765.     int fd;
  766.     char **bpp;
  767.     int size;
  768. {
  769.     return (0);
  770. }
  771.  
  772. EXPORT void
  773. fifo_stats()
  774. {
  775. }
  776.  
  777. EXPORT int
  778. fifo_percent(addone)
  779.     BOOL    addone;
  780. {
  781.     return (-1);
  782. }
  783.  
  784. #endif    /* FIFO */
  785.